package com.ycher.hellokotlin.first

import kotlin.math.max

/**
 * 第一行代码
 * Learn Kotlin
 */
fun main() {
//    kotlinBasics()
    objectOriented()
}

fun kotlinBasics() {
    // sout 快捷打印
    println("I love Han Shuang forever.")

    // val（value的简写）    用来声明一个不可变的变量，这种变量在初始赋值之后就再也不能重新赋值，对应 Java 中的 final 变量。
    // var（variable的简写） 用来声明一个可变的变量，这种变量在初始赋值之后仍然可以再被重新赋值，对应 Java 中的非 final 变量。
    val a = 10
//    println("a = " + a)

    var b: Int = 10
    b *= 10
//    println("b = " + b)

    // 函数
    val max1 = largerNumber(524, 114)
    val max2 = largerNumberOnly(422, 1125)
    val max3 = largerNumberSimp(2021, 2022)
//    println("max1 = " + max1 + "; " + "max2 = " + max2 + "; " + "max3 = " + max3)

    // 条件
//    checkNumber(3.1415926)
//    checkNumber(1125L)

    // 循环
//    forinCycle()
    whileCycle()
}

fun objectOriented() {
    // 实例化，并操作对象
//    val p = Person()
//    p.name = "Jack"
//    p.age = 18
//    p.eat()

    // 继承
//    val s = Student("GB007", 3)
//    s.name = "Small"
//    s.age = 6
//    s.eat()

    // 构造
//    val s1 = Student1()
//    val s2 = Student1("Jack", 19)
//    val s3 = Student1("A123", 5, "Jack", 19)

    // 面向接口编程（多态）
//    val student = StudentByInterface("Tom",8)
//    doStudy(student)

    // 数据类
    val phone1 = Cellphone("Samsung", 1299.99)
    val phone2 = Cellphone("Samsung", 1299.99)
    println(phone1)
    println("Cellphone1 equals Cellphone2 " + (phone1 == phone2))

    // 单例类
    Singleton.singletonTest()
}

fun doStudy(student: StudentByInterface) {
    student.readBooks()
    student.doHomework()
}

/// 函数
fun largerNumber(n1: Int, n2: Int): Int {
    return max(n1, n2)
}

// 当一个函数中只有一行代码时，Kotlin 允许我们不必编写函数体，可以直接将唯一的一行代码写在函数定义的尾部，中间用等号连接即可。
fun largerNumberOnly(n1: Int, n2: Int): Int = max(n1, n2)

// 类型推倒简化写法
fun largerNumberSimp(n1: Int, n2: Int) = max(n1, n2)

/// if 条件语句
fun ifCondition1(n1: Int, n2: Int): Int {
    var value = 0
    if (n1 > n2) {
        value = n1
    } else {
        value = n2
    }
    return value
}

fun ifCondition2(n1: Int, n2: Int): Int {
    val value = if (n1 > n2) {
        n1
    } else {
        n2
    }
    return value
}

fun ifCondition3(n1: Int, n2: Int): Int {
    return if (n1 > n2) {
        n1
    } else {
        n2
    }
}

fun ifCondition4(n1: Int, n2: Int) = if (n1 > n2) n1 else n2

/// when 条件语句
// 格式：匹配值 -> { 执行逻辑 }
fun getScore(name: String) = when (name) {
    "Tom" -> 86
    "Jim" -> 77
    "Jack" -> 95
    "Lily" -> 100
    else -> 0
}

// Number 是 Kotlin 内置的一个抽象类，像 Int、Long、Float、Double 等与数字相关的类都是它的子类
fun checkNumber(num: Number) {
    when (num) {
        // is 关键字就是类型匹配的核心，它相当于 Java 中的 instanceof 关键字
        is Int -> println("number is Int")
        is Double -> println("number is Double")
//        is Long -> println("number is Long")
        else -> println("number not support")
    }
}

// Kotlin 中判断字符串或对象是否相等可以直接使用 == 关键字，而不用像 Java 那样调用 equals() 方法
fun getScoreStr(name: String) = when {
    name.startsWith("Tom") -> 86
    name == "Jim" -> 77
    name == "Jack" -> 95
    name == "Lily" -> 100
    else -> 0
}

/// for-in 循环
fun forinCycle() {
    // 区间 [0, 10]   双端闭区间却不如单端闭区间好用
    println("\n=== 双闭区间 ===")
    val range = 0..10
    for (i in range) println(i)

    // 区间 [0, 10)   左闭右开的区间在程序设计当中更加常用
    println("\n=== 左闭右开 ===")
    val rangeUntil = 0 until 10
    for (i in rangeUntil) println(i)

    // 默认情况下，for-in 循环每次执行循环时会在区间范围内递增 1，相当于 Java for-i 循环中 i++ 的效果
    // 如果你想跳过其中的一些元素，可以使用 step 关键字，相当于 Java for-i 循环中 i+=2 的效果
    println("\n=== Step ===")
    val rangeStep = 0 until 10
    for (i in rangeStep step 2) println(i)

    // 降序区间 [10, 1] downTo (.. 与 until 都为升序区间)
    println("\n=== 降序区间 downTo ===")
    val rangeDownTo = 10 downTo 1
    for (i in rangeDownTo) println(i)

}

/// while 循环
fun whileCycle() {
    // 先问后做
    println("\n=== while ===")
    var x = 3
    while (x > 0) {
        x--
        println(x)
    }

    // 先做再问
    println("\n=== do while ===")
    var y = 10
    do {
        y -= 3
        println(y)
    } while (y > 0) // y 在此处可见
}